﻿using DotNetty.Codecs.Http.WebSockets;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using System;

namespace DotNetty.Framework
{
    public class CommonChannelHandler<TMessage> : SimpleChannelInboundHandler<object>
        where TMessage : AbstractMessage
    {

        IWebSocketEventTriggered<TMessage> eventTriggered;

        public CommonChannelHandler(IWebSocketEventTriggered<TMessage> eventTriggered)
        {
            this.eventTriggered = eventTriggered;
        }



        protected override void ChannelRead0(IChannelHandlerContext context, object msg)
        {
            if (Common.IsShutdowned)
            {
                return;
            }

            if (msg is WebSocketFrame frame)
            {
                this.UserEventTriggered(context, frame);
            }
        }


        public override void ChannelInactive(IChannelHandlerContext context) 
        {
            // 用户下线
            Console.WriteLine("ChannelInactive:" + DateTime.Now);
            this.eventTriggered.OnClose(context);
            base.ChannelInactive(context);
        }

        /// <summary>
        /// 用户自定义事件
        /// </summary>
        /// <param name="context"></param>
        /// <param name="evt"></param>
        public override void UserEventTriggered(IChannelHandlerContext context, object evt)
        {
            try
            {
                this.eventTriggered.UserEventTriggered(context, evt);

                if (evt is IdleStateEvent eventState)
                {

                    if (eventState.State == IdleState.ReaderIdle)
                    {
                        this.CloseAsync(context);
                        //this.eventTriggered.OnClose(context);
                        Console.WriteLine($"IdleState.ReaderIdle:" + DateTime.Now);
                    }
                    else if (eventState.State == IdleState.WriterIdle)
                    {
                        Console.WriteLine("IdleState.WriterIdle:" + DateTime.Now);
                    }
                }
                else if (evt is CloseWebSocketFrame frame)
                {
                    //this.eventTriggered.OnClose(context);
                    this.CloseAsync(context);
                }
                else if (evt is PongWebSocketFrame pong)
                {
                    Console.WriteLine(pong.ToString());
                }
                else
                {
                    base.UserEventTriggered(context, evt);
                }
            }
            catch (Exception ex)
            {
                this.eventTriggered.OnError(context, new OnExceptionContext
                {
                    Action = "CommonChannelHandler.UserEventTriggered",
                    Exception = ex,
                    Message = evt
                });
            }
        }


        /// <summary>
        /// 出现异常
        /// </summary>
        /// <param name="context"></param>
        /// <param name="exception"></param>
        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            if (exception.Message.Equals("refCnt: 0, decrement: 1"))
            {
                return;
            }
            Console.WriteLine("Exception: " + exception.Message);

            if (exception.Message.Equals("Exception of type 'DotNetty.Transport.Channels.ChannelException' was thrown."))
            {
                //this.eventTriggered.OnClose(context);
                return;
            }

            try
            {
                context.CloseAsync();
                this.eventTriggered.OnError(context, new OnExceptionContext
                {
                    Action = "CommonChannelHandler.ExceptionCaught",
                    Exception = exception
                });
            }
            catch
            {
            }
        }

        //public virtual void CloseAsync(IChannelHandlerContext context, CloseWebSocketFrame frame)
        //{
        //    this.Handshaker.CloseAsync(context.Channel, frame);
        //}
    }
}
